<!--
* @author luguoxiang
* @date 2021-09-07
* 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
-->
<template>
  <slot :label="labelValue" :open="openModal" :clear="clear" :remove-item="remove">
    <div class="t-input" :class="{ 't-is-disabled': props.disabled }" @click="openModal">
      <div v-if="props.multiple" class="t-input__prefix">
        <t-tag v-for="(x, i) in labelValue" :closable="clearable" @click.stop @close="remove(i)">{{ x }}</t-tag>
      </div>
      <template v-else>
        {{ labelValue?.[0] }}
      </template>
      <div v-if="clearable && labelValue.length" class="icon-close" @click.stop="clear">
        <close-icon />
      </div>
    </div>
  </slot>
  <lg-modal ref="modelRef" v-bind="modalProps" @confirm="ok">
    <div style="height: 500px">
      <lg-table :schema="props.schema" v-bind="tableProps"> </lg-table>
    </div>
  </lg-modal>
</template>

<script lang="ts" setup>
import { computed, ref, useAttrs, watch } from 'vue';
import { CloseIcon } from 'tdesign-icons-vue-next';
import {
  distinct,
  formatStr,
  IConfigSchema,
  ITableSchema,
  LgModal,
  LgTable,
  LgTableProps,
  toAsyncLoader,
  useTable,
  UseTableOptions,
} from '@/soar';

interface Props {
  modelValue?: any;
  /**
   * 弹窗标题
   */
  title?: string;
  /**
   * 多选
   */
  multiple?: boolean;
  /**
   * 可清空
   */
  clearable?: boolean;
  /**
   * 只读
   */
  readonly?: boolean;
  /**
   * 禁用
   */
  disabled?: boolean;
  /**
   * label格式，例：field 或 ${field1}（${field2}）
   * 非必填
   */
  labelField?: string;
  /**
   * 数据配置
   */
  data: Function | string | Object[];
  /**
   * 表格配置
   */
  schema: IConfigSchema<any> | ITableSchema<any>;
  /**
   * 值格式或字段，例：field 或 ${field1}-${field2}
   * 非必填
   */
  rowKey?: string;
  /**
   * 加载选项名称
   */
  handleLabel?(values): string[] | Promise<string[]>;
  /**
   * 弹窗配置
   */
  modalProps?: any;
}
const props = defineProps<Props>();
const emits = defineEmits(['update:modelValue', 'change']);
const attrs = useAttrs();
const modelRef = ref();

const rowKey = props.rowKey || 'id';
const labelField = props.labelField || props.schema[0]?.field;
const fields = distinct(formatStr.getPatternKeys(labelField));

const labelValue = ref([]);
const clearable = computed(() => {
  if (props.disabled || props.readonly) {
    return false;
  }
  return props.clearable;
});
const loader = computed(() => toAsyncLoader(props.data));
const handleLabel = toAsyncLoader(
  props.handleLabel ||
    ((v) => {
      if (v === null || v === undefined || (Array.isArray(v) && !v.length)) {
        return Promise.resolve([]);
      }
      return loader.value({ queryType: 'list', fields, $soarQuery: { [`${rowKey}-in`]: v } }).then((res) => {
        if (Array.isArray(res)) {
          res = { list: res };
        }
        return res.list.map((x: any) => formatStr(labelField, x));
      });
    }),
);

const modalProps = computed(() => {
  return {
    header: props.title,
    draggable: true,
    width: 1200,
    height: 500,
    ...props.modalProps,
  };
});

const { tableProps, tableRef, selectedKeys, getSelectRows, reload } = useTable<any>({
  rowKey,
  api: { query: props.data },
  props: {
    searchbar: true,
    actionbar: false,
    selection: props.multiple ? true : { colKey: 'row-select', type: 'single' },
    immediate: false,
    tableProps: {
      selectOnRowClick: true,
      onCellClick: null,
      ...attrs,
    },
  } as LgTableProps,
} as UseTableOptions);

watch(
  () => props.modelValue,
  (v) => {
    handleLabel(v).then((res) => {
      labelValue.value = res;
    });
  },
  { immediate: true },
);

function ok() {
  updateValue(selectedKeys.value);
  modelRef.value.close();
}

function updateValue(sks) {
  if (props.multiple) {
    emits('update:modelValue', sks);
    emits('change', getSelectRows());
  } else {
    emits('update:modelValue', sks[0]);
    emits('change', getSelectRows()[0]);
  }
}

function clear() {
  updateValue([]);
}

function remove(i) {
  updateValue(props.modelValue.filter((x, index) => index !== i));
}

function openModal() {
  if (props.readonly || props.disabled) {
    return;
  }
  if (props.multiple) {
    tableRef.value.select(props.modelValue);
  } else {
    tableRef.value.select([props.modelValue]);
  }
  modelRef.value.open();
  reload(1);
}

defineExpose({
  tableRef,
  modelRef,
});
</script>
<script lang="ts">
export default {
  name: 'LgPicker',
};
</script>

<style lang="less" scoped>
:deep(.t-dialog__body) {
  padding: 0;
}
:deep(.t-tag) {
  margin-right: 3px;
}
.t-input {
  &:hover {
    .icon-close {
      display: flex;
    }
  }
}
.icon-close {
  display: none;
  align-items: center;
  padding: 0 3px;
  cursor: pointer;
  position: absolute;
  right: 8px;
  .t-icon {
    color: #fff;
    border-radius: 50%;
    background-color: var(--app-color-placeholder);
    &:hover {
      background-color: var(--app-color-text-secondary);
    }
  }
}
</style>
